package com.k.sshm.boot.web.servlet.container.inf.aop.log;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.lang.reflect.Method;

@Slf4j
@Component
@Aspect
public class LogStdOut {

    private final ObjectMapper objectMapper = new ObjectMapper();
    @Value("${low-method-time: 5000}")
    private long maxReduceTime;

    @Pointcut("execution(* com.k.sshm.boot.web.servlet.container.control..*.*(..))")
    private void logPoint() {
    }

    @Around("logPoint()")
    public Object processLog(ProceedingJoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        Class<?>[] argTypes = new Class[joinPoint.getArgs().length];
        for (int i = 0; i < args.length; i++) {
            argTypes[i] = args[i].getClass();
        }
        Method method = joinPoint.getTarget().getClass().getMethod(joinPoint.getSignature().getName(), argTypes);
        //method.getDeclaredAnnotation(LogApi.class);
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        Assert.notNull(attributes, "请求参数null异常");
        HttpServletRequest request = attributes.getRequest();
        String methodName = method.getName();
        log.info("================== start ==================");
        log.info("请求URL:  {}", request.getRequestURL().toString());
        log.info("请求类型:  {}", request.getMethod());
        log.info("请求Controller:  {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        try {
            log.info("请求入参:  {}", objectMapper.writeValueAsString(args));
        } catch (JsonProcessingException e) {
            log.error("获取请求参数失败");
        }
        long startTime = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long endTime = System.currentTimeMillis();
        this.printExecTime(methodName, startTime, endTime);
        if (proceed != null) {
            try {
                log.info("请求出参:  {}", objectMapper.writeValueAsString(proceed));
            } catch (JsonProcessingException e) {
                log.error("获取出参信息失败");
            }
        } else {
            log.info("请求出参:  无出参信息");
        }
        log.info("=================== end ===================");
        return proceed;
    }

    private void printExecTime(String methodName, long startTime, long endTime) {
        long diffTime = endTime - startTime;
        if (diffTime > maxReduceTime) {
            log.info("可能慢接口:  " + methodName + "方法执行耗时:" + diffTime + " ms");
        } else {
            log.info(methodName + " 方法执行耗时:" + diffTime + " ms");
        }
    }
}